﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Seems.Framework.Extensions;
using Seems.View.Controls;

namespace Seems.View.Behaviors
{
	public class Panorama : Behavior<Contour>
	{
		private bool isPanning;
		private Point startPosition;
		private ScrollViewer scroller;
		private Image cursor;
		private ScaleTransform scaleTransform;

		public ScrollViewer Scroller
		{
			get { return scroller ?? (scroller = AssociatedObject.Ancestors<ScrollViewer>().First()); }
		}

		protected override void OnAttached()
		{
			AssociatedObject.MouseLeftButtonDown += OnPanStart;
			AssociatedObject.MouseLeftButtonUp += OnPanEnd;
			AssociatedObject.MouseMove += OnPanMove;
		}

		protected override void OnDetaching()
		{
			AssociatedObject.MouseLeftButtonDown -= OnPanStart;
			AssociatedObject.MouseLeftButtonUp -= OnPanEnd;
			AssociatedObject.MouseMove -= OnPanMove;
		}


		private void OnPanStart(object sender, MouseButtonEventArgs e)
		{
			isPanning = true;
			startPosition = e.GetPosition(AssociatedObject);
			AssociatedObject.CaptureMouse();
			//ShowDragCursor();
		}

		private void OnPanEnd(object sender, MouseButtonEventArgs e)
		{
			isPanning = false;
			AssociatedObject.ReleaseMouseCapture();
			HideDragCursor();
		}


		private void HideDragCursor()
		{
			if (cursor != null)
			{
				cursor.Visibility = Visibility.Collapsed;
				AssociatedObject.Children.Remove(cursor);
				AssociatedObject.Cursor = Cursors.Arrow;
			}
		}

		private void ShowDragCursor()
		{
			if (cursor == null)
			{
				cursor = new Image
					{
						Width = 16,
						Height = 16,
						Margin = new Thickness(0),
						Cursor = Cursors.None,
						VerticalAlignment = VerticalAlignment.Top,
						HorizontalAlignment = HorizontalAlignment.Left,
						IsHitTestVisible = false,
						RenderTransform = new TranslateTransform(),
						Source = new BitmapImage(new Uri("/Seems;component/Assets/Cursors/cursor_drag_hand.png", UriKind.Relative))
					};
				cursor.SetValue(Canvas.LeftProperty, startPosition.X);
				cursor.SetValue(Canvas.TopProperty, startPosition.Y);
				AssociatedObject.Children.Add(cursor);
				AssociatedObject.Cursor = Cursors.None;
			}
		}

		private void OnPanMove(object sender, MouseEventArgs e)
		{
			var currentPosition = e.GetPosition(AssociatedObject);

			if (isPanning)
			{
				//var transform = (TranslateTransform)cursor.RenderTransform;
				//transform.X = currentPosition.X;
				//transform.Y = currentPosition.Y;

				// Work out the delta between the last sample and the current position
				var delta = new Point(currentPosition.X - startPosition.X, currentPosition.Y - startPosition.Y);

				// Transform delta according to zoom
				if (scaleTransform == null)
				{
					var group = ((TransformGroup)AssociatedObject.RenderTransform).Children;
					scaleTransform = (ScaleTransform)group.First(t => t is ScaleTransform);
				}
				//var translateTransform = (TranslateTransform)group.First(t => t is TranslateTransform);
				delta.X /= (double)scaleTransform.GetValue(ScaleTransform.ScaleXProperty);
				delta.Y /= (double)scaleTransform.GetValue(ScaleTransform.ScaleXProperty);

				// Reset last sample to new one ready for next cycle.
				//startPosition = currentPosition;

				Scroller.ScrollToHorizontalOffset(- delta.X);
				Scroller.ScrollToVerticalOffset(- delta.Y);
/*
				// Calculate the newly transformed X and Y coordinates by offsetting the delta
				var newTransformX = translateTransform.X + delta.X;
				var newTransformY = translateTransform.Y + delta.Y;
				Debug.WriteLine(string.Format("Delta = {0},{1} NewTranslate = {2},{3}", delta.X, delta.Y, translateTransform.X, translateTransform.Y));

				// Trim new transform into bounds of the element bounds - IE we can only drag the canvas to
				// pan within the constraints of the entities themselves + a gutter.
//				if ((newTransformX * -1) > currentBounds.Left && (newTransformX * -1) < currentBounds.Right)
				{
					translateTransform.X = newTransformX;
				}

//				if ((newTransformY * -1) > currentBounds.Top && (newTransformY * -1) < currentBounds.Bottom)
				{
					translateTransform.Y = newTransformY;
				}
*/
			}
		}
	}
}
